<?php
/**
 * Store's management class
 *
 * @access		public
 * @author		Svilen Spasov <svilen@svilen.com>
 * @package		AMBilling System
 *
 * @since			28-02-2006
 * @version		1.9
 */
class Store {
	/**
	 * Db Object
	 * @access   private
	 * @var 		 object
	 */
	var $anydb;
	
	/**
	 * error handler
	 * @access   private
	 * @var 		 object
	 */
	var $error;
	
	/**
	 * storeId
	 * @access   private
	 * @var 		 int
	 */
	var $storeId;
	
	/**
	 * Reseller Id
	 * @access   private
	 * @var 		 int
	 */
	var $resellerId;
	
	/**
	 * Store name
	 * @access   private
	 * @var 		 string
	 */
	var $storeName;
	
	/**
	 * Store title
	 * @access   public
	 * @var 		 string
	 */
	var $storeTitle;
	
	/**
	 * Store currency
	 * @access   public
	 * @var 		 string
	 */
	var $storeCurrency;
	
	/**
	 * Store language
	 * @access   public
	 * @var 		 string
	 */
	var $storeLanguage;
	
	/**
	 * Store template
	 * @access   public
	 * @var 		 int
	 */
	var $storeTemplate;
	
	/**
	 * Store products
	 * @access   public
	 * @var 		 array
	 */
	var $storeProducts;
	
	/**
	 * Product
	 * @access   public
	 * @var 		 array
	 */
	var $product = array();
	
	/**
	 * Constructor defines basic objects
	 *
	 * @access   public
	 * @author   Svilen Spasov <svilen@svilen.com>
	 *
	 * @param 	 object		$db						AnyDb object
	 * @param 	 int			$resellerId		Reseller Id
	 * @param 	 string		$storeName		Store name
	 * @param 	 int			$storeId			Store Id
	 *
	 * @see 		 Error::addError()
	 *
	 * @since    02-03-2006
	 * @version  1.0
	 */
	function Store($db, $resellerId = NULL, $storeName = NULL, $storeId = NULL) {
		$this->error = new Error();
		$this->anydb = $db;
		
		if (!empty($resellerId)) {
			$this->resellerId = $resellerId;
			// get store details
			$this->getStoreDetails ('resellerId');
		}
		elseif (!empty($storeName)) {
			$this->storeName = $storeName;
			// get store details
			$this->getStoreDetails ('storeName');
		}
		elseif (!empty($storeId)) {
			$this->storeId = $storeId;
			// get store details
			$this->getStoreDetails ('storeId');
		}
		else {
			$this->error->addError (1, 'Improper params passed to Store class', FATAL_ERROR, true);
		}
		
		// get store products
		$this->getProducts();
		// set products' currency
		$this->setProductsCurrency($this->storeCurrency);
	}
	
	/**
	 * Get store details by store name
	 *
	 * @access   public
	 * @author   Svilen Spasov <svilen@svilen.com>
	 *
	 * @param 	 string		$by				Select by type
	 *
	 * @see			 AnyDB::query()
	 * @see			 AnyDB::getNext()
	 * @see 		 Error::addError()
	 *
	 * @since    02-03-2006
	 * @version  1.0
	 */
	function getStoreDetails ($by) {
		switch ($by) {
			case 'resellerId':
				$resellerId = (int) $this->resellerId;
				
				if (empty($resellerId)) {
					$this->error->addError(2, 'Wrong params for getStoreDetails() method in Store class');
					return FALSE;
				}
				
				$where = "reseller_id = $resellerId";
				break;
			case 'storeId':
				$storeId = (int) $this->storeId;
				
				if (empty($storeName)) {
					$this->error->addError(3, 'Wrong params for getStoreDetails() method in Store class');
					return FALSE;
				}
				
				$where = "store_id = $storeId";
				break;
			case 'storeName':
			default:
				$storeName = $this->anydb->escapeStr($this->storeName);
				
				if (empty($storeName)) {
					$this->error->addError(4, 'Wrong params for getStoreDetails() method in Store class');
					return FALSE;
				}
				
				$where = "name = '$storeName'";
				break;
		}
		
		$query = <<<echo
SELECT store_id as store_id, reseller_id as reseller_id, title as title, currency as currency, language as language, template as template, products as products, name as name FROM stores WHERE $where LIMIT 1
echo;
		$this->anydb->query($query);
		
		// check for error
		if (!empty($this->anydb->error)) {
			$this->error->addError(3, $this->anydb->error);
			return FALSE;
		}
		
		// get values
		$recordSet = $this->anydb->getNext();
		$this->storeId = $recordSet['store_id'];
		$this->resellerId = $recordSet['reseller_id'];
		$this->storeName = $recordSet['name'];
		$this->storeTitle = $recordSet['title'];
		$this->storeCurrency = $recordSet['currency'];
		$this->storeLanguage = $recordSet['language'];
		$this->storeTemplate = $recordSet['template'];
		$this->storeProducts = decodeDbStrings($recordSet['products']);
		
		return TRUE;
	}
	
	/**
	 * Get store products
	 *
	 * @access   public
	 * @author   Svilen Spasov <svilen@svilen.com>
	 *
	 * @see			 AnyDB::query()
	 * @see			 AnyDB::getAll()
	 * @see 		 Error::addError()
	 *
	 * @since    02-03-2006
	 * @version  1.0
	 */
	function getProducts () {
		$recordSet = array();
		$productId = '';
		$storeId = $this->anydb->escapeStr($this->storeId);
		
		if (empty($storeId)) {
			$this->error->addError(5, 'Wrong params for getStoreDetails() method in Store class');
			return FALSE;
		}
				
		$query = <<<echo
SELECT product_id as product_id FROM products WHERE store_id = $storeId
echo;
		$this->anydb->query($query);
		
		// check for error
		if (!empty($this->anydb->error)) {
			$this->error->addError(3, $this->anydb->error);
			return FALSE;
		}
		
		$recordSet = $this->anydb->getAll();
		foreach ($recordSet as $key => $value) {
			$productId = $value['product_id'];
			$this->product[$productId] = new Product(&$this->anydb, &$this->error, $productId);
		}
	}
	
	/**
		* Sets detauls currency to all products objects
		*
		* @access   public
		* @author   Svilen <svilen@svilen.com>
		*
		* @param		string		$currency			Currency string
		*
		* @return		bool			TRUE/FALSE
		*
		* @since    02-03-2006
		* @version  1.0
		*
		*/
	function setProductsCurrency ($currency = 'USD') {
		if (empty($currency)) {
			return FALSE;	
		}
		
		foreach ($this->product as $key => $value) {
			$this->product[$key]->setPriceCurrency($currency);
		}
				
		return TRUE;
	}
	
	/**
		* Sets default period to all products objects
		*
		* @access   public
		* @author   Svilen <svilen@svilen.com>
		*
		* @param		int				$period			Period value
		*
		* @return		bool			TRUE/FALSE
		*
		* @since    02-03-2006
		* @version  1.0
		*
		*/
	function setProductsPeriod ($period = 12) {
		if (empty($period)) {
			return FALSE;	
		}
		
		foreach ($this->product as $key => $value) {
			$this->product[$key]->setPricePeriod($period);
		}
		
		return TRUE;
	}
	
	/**
		* Sort all products in the internal product array
		*
		* @access   public
		* @author   Svilen  Spasov<svilen@svilen.com>
		*
		* @since    07-03-2006
		* @version  1.0
		*/
	function sortProducts () {
		usort ($this->product, array ('Store', 'compareProducts'));
		
		// usort removes our keys from Store::product so we have to assign them again
		foreach ($this->product as $key => $value) {
			$this->product[$value->productId] = $value;
			unset($this->product[$key]);
		}
	}
	
	/**
		* Internal method for sorting products
		*
		* @access   private
		* @author   Svilen  Spasov <svilen@svilen.com>
		*
		* @param		object				$a			First object
		* @param		object				$b			Second object
		*
		* @return		int				0/-1/1
		*
		* @since    07-03-2006
		* @version  1.0
		*/
	function compareProducts ($a, $b) {
		if(!empty($a->seq) && !empty($b->seq)) {
			if ($a->seq > $b->seq) {
				return 1;
			}
			elseif ($a->seq < $b->seq) {
				return -1;
			}
			else {
				return 0;
			}
		}
		else if($a->wholesale->get() > $b->wholesale->get()) {
			return 1;
		}
		else if($a->wholesale->get() < $b->wholesale->get()) {
			return -1;
		}
		else {
			return 0;
		}
	}
	
	/**
		* Returns plan id by plan name
		*
		* @access   public
		* @author   Svilen  Spasov <svilen@svilen.com>
		*
		* @param		string			$planName			Plan name
		*
		* @return		int				Plan's product id
		*
		* @since    07-03-2006
		* @version  1.0
		*/
	function getSelectedPlanIdByPlanName ($planName = '') {
		if (empty($planName)) {
			return FALSE;
		}
		
		foreach ($this->product as $key => $value) {
			if ($value->type == 'plan' && strtolower($planName) == strtolower($value->name)){
				return $value->productId;
				break;
			}
		}
	}
	
	/**
		* Returns TRUE/FALSE if a plan is offered on the store
		*
		* @access   public
		* @author   Svilen  Spasov <svilen@svilen.com>
		*
		* @param		int			$productId			Plan id
		*
		* @return		bool		TRUE/FALSE
		*
		* @since    08-03-2006
		* @version  1.0
		*/
	function isOfferedPlan ($productId = NULL) {
		if (empty($productId)) {
			return FALSE;
		}
		
		return Store::inArrayKey($productId, $this->storeProducts['plans_offering']);
	}
	
	/**
		* Returns TRUE/FALSE if a domain product is offered on the store
		*
		* @access   public
		* @author   Svilen  Spasov <svilen@svilen.com>
		*
		* @param		int			$productId			Plan id
		*
		* @return		bool		TRUE/FALSE
		*
		* @since    08-03-2006
		* @version  1.0
		*/
	function isOfferedDomain ($productId = NULL) {
		if (empty($productId)) {
			return FALSE;
		}
		
		return Store::inArrayKey($productId, $this->storeProducts['domains_offering']);
	}
	
	/**
		* Returns product periods
		*
		* @access   public
		* @author   Svilen  Spasov <svilen@svilen.com>
		*
		* @param		int			$productId			Product id
		*
		* @return		array		Product periods
		*
		* @since    09-03-2006
		* @version  1.0
		*/
	function getProductPeriods ($productId = NULL) {
		if (empty($productId)) {
			return FALSE;
		}
		
		return Store::arrayKeysTrue($this->storeProducts['periods'][$productId]);
	}
	
	/**
		* Returns domains free product periods
		*
		* @access   public
		* @author   Svilen  Spasov <svilen@svilen.com>
		*
		* @param		int			$productId			Product id
		* @param		int			$productId			Period
		*
		* @return		array		Domains free products
		*
		* @since    09-03-2006
		* @version  1.0
		*/
	function isAvailableFreeDomain ($productId = NULL, $period = NULL) {
		if (empty($productId) || empty($period)) {
			return FALSE;
		}
		
		if (Store::inArrayKey($productId, $this->storeProducts['domains_free'])) {
			return Store::inArrayKey($period, $this->storeProducts['domains_free'][$productId]);
		}
		else {
			return FALSE;
		}
	}
	
	/**
		* Returns real plan price in currenlty set currency (includes free domain offer)
		*
		* @access   public
		* @author   Svilen  Spasov <svilen@svilen.com>
		*
		* @param		int			$productId			Product id
		* @param		string	$priceType			Price type
		* @param		int			$productId			Period
		*
		* @return		float		Plan price
		*
		* @since    15-03-2006
		* @version  1.0
		*/
	function getRealPlanPrice ($productId, $priceType = 'price', $period = 12, $currency = NULL) {
		$price = '';
		
		if (empty($productId) || empty($priceType) || empty($period)) {
			return FALSE;
		}
		
		if (Store::inArrayKey($productId, $this->product)) {
			if ($this->isAvailableFreeDomain($productId, $period)) {
				$price = $this->product[$productId]->getTotalPriceByType ($priceType, $period, $currency) + $this->getFreeDomainPrice($priceType, $period, $currency);
			}
			else {
				$price = $this->product[$productId]->getTotalPriceByType ($priceType, $period, $currency);
			}
		}
		
		return $price;
	}
	
	/**
		* Returns FREE domain product price
		*
		* @access   public
		* @author   Svilen  Spasov <svilen@svilen.com>
		*
		* @param		string	$priceType			Price type
		* @param		int			$productId			Period
		*
		* @return		float		FREE domain price
		*
		* @since    15-03-2006
		* @version  1.0
		*/
	function getFreeDomainPrice ($priceType = 'price', $period = 12, $currency = NULL) {
		$price = '';
		
		if (empty($priceType) || empty($period)) {
			return FALSE;
		}
		
		foreach ($this->product as $key => $value) {
			if ($value->type == 'domain') {
				$price = $this->product[$key]->getTotalPriceByType ($priceType, $period, $currency);
			}
		}
		
		return $price;
	}
	
	/**
		* Returns TRUE/FALSE if a given value is found as a key in an array and it's corresponding value is not empty
		*
		* @access   public
		* @author   Svilen  Spasov <svilen@svilen.com>
		*
		* @param		mixed			$value			Searched key
		* @param		array			$array			Input array
		*
		* @return		bool			TRUE/FALSE
		*
		* @since    15-03-2006
		* @version  1.0
		*/
	function inArrayKey ($value, $array) {
		if (!is_array($array)) {
			return FALSE;
		}
		
		foreach ($array as $k => $v) {
			if ($k == $value && !empty($v)) {
				return TRUE;
			}
		}
		
		return FALSE;
	}
	
	/**
		* Extracts only key with not empty value from array
		*
		* @access   public
		* @author   Svilen  Spasov <svilen@svilen.com>
		*
		* @param		array			$array			Input array
		*
		* @return		array			Array with stripped empty elements
		*
		* @since    15-03-2006
		* @version  1.0
		*/
	function arrayKeysTrue ($array) {
		$result = array ();
		
		foreach ($array as $k => $v) {
			if (!empty($v)) {
				$result[] = $k;
			}
		}
		
		return $result;
	}
}
?>